package com.docmgmt.mvp.controller;

import com.docmgmt.mvp.dto.Result;
import com.docmgmt.mvp.ragflow.RAGFlowLLMClient;
import com.docmgmt.mvp.service.LLMService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;

/**
 * LLM管理控制器
 * 提供LLM模型查询相关的REST API
 */
@Slf4j
@RestController
@RequestMapping("/api/v1/llm")
@Tag(name = "LLM管理", description = "LLM模型查询和管理接口")
public class LLMController {

    @Autowired
    private LLMService llmService;

    /**
     * 获取所有已配置的LLM模型列表
     *
     * @return LLM模型列表
     */
    @GetMapping("/list")
    @Operation(summary = "获取LLM列表", description = "获取当前租户配置的所有LLM模型")
    public Result<List<LLMModelDTO>> listLLMs() {
        try {
            log.info("收到查询LLM列表请求");
            List<RAGFlowLLMClient.LLMModel> models = llmService.getMyLLMs();

            // 转换为DTO（隐藏API密钥等敏感信息）
            List<LLMModelDTO> dtos = models.stream()
                    .map(this::convertToDTO)
                    .collect(Collectors.toList());

            log.info("成功返回LLM列表: 共{}个模型", dtos.size());
            return Result.success(dtos);
        } catch (Exception e) {
            log.error("查询LLM列表失败", e);
            return Result.error("ERROR", "查询LLM列表失败: " + e.getMessage());
        }
    }

    /**
     * 获取聊天模型列表（仅chat类型）
     *
     * @return 聊天模型列表
     */
    @GetMapping("/chat")
    @Operation(summary = "获取聊天模型列表", description = "获取所有chat类型的LLM模型")
    public Result<List<LLMModelDTO>> listChatModels() {
        try {
            log.info("收到查询聊天模型列表请求");
            List<RAGFlowLLMClient.LLMModel> models = llmService.getChatModels();

            List<LLMModelDTO> dtos = models.stream()
                    .map(this::convertToDTO)
                    .collect(Collectors.toList());

            log.info("成功返回聊天模型列表: 共{}个模型", dtos.size());
            return Result.success(dtos);
        } catch (Exception e) {
            log.error("查询聊天模型列表失败", e);
            return Result.error("ERROR", "查询聊天模型列表失败: " + e.getMessage());
        }
    }

    /**
     * 获取嵌入模型列表（仅embedding类型）
     *
     * @return 嵌入模型列表
     */
    @GetMapping("/embedding")
    @Operation(summary = "获取嵌入模型列表", description = "获取所有embedding类型的LLM模型")
    public Result<List<LLMModelDTO>> listEmbeddingModels() {
        try {
            log.info("收到查询嵌入模型列表请求");
            List<RAGFlowLLMClient.LLMModel> models = llmService.getEmbeddingModels();

            List<LLMModelDTO> dtos = models.stream()
                    .map(this::convertToDTO)
                    .collect(Collectors.toList());

            log.info("成功返回嵌入模型列表: 共{}个模型", dtos.size());
            return Result.success(dtos);
        } catch (Exception e) {
            log.error("查询嵌入模型列表失败", e);
            return Result.error("ERROR", "查询嵌入模型列表失败: " + e.getMessage());
        }
    }

    /**
     * 获取重排序模型列表（仅rerank类型）
     *
     * @return 重排序模型列表
     */
    @GetMapping("/rerank")
    @Operation(summary = "获取重排序模型列表", description = "获取所有rerank类型的LLM模型")
    public Result<List<LLMModelDTO>> listRerankModels() {
        try {
            log.info("收到查询重排序模型列表请求");
            List<RAGFlowLLMClient.LLMModel> models = llmService.getRerankModels();

            List<LLMModelDTO> dtos = models.stream()
                    .map(this::convertToDTO)
                    .collect(Collectors.toList());

            log.info("成功返回重排序模型列表: 共{}个模型", dtos.size());
            return Result.success(dtos);
        } catch (Exception e) {
            log.error("查询重排序模型列表失败", e);
            return Result.error("ERROR", "查询重排序模型列表失败: " + e.getMessage());
        }
    }

    /**
     * 获取LLM工厂列表
     *
     * @return LLM工厂列表
     */
    @GetMapping("/factories")
    @Operation(summary = "获取LLM工厂列表", description = "获取所有可用的LLM提供商")
    public Result<List<RAGFlowLLMClient.LLMFactory>> listFactories() {
        try {
            log.info("收到查询LLM工厂列表请求");
            List<RAGFlowLLMClient.LLMFactory> factories = llmService.getFactoryList();
            log.info("成功返回LLM工厂列表: 共{}个工厂", factories.size());
            return Result.success(factories);
        } catch (Exception e) {
            log.error("查询LLM工厂列表失败", e);
            return Result.error("ERROR", "查询LLM工厂列表失败: " + e.getMessage());
        }
    }

    /**
     * 验证LLM ID是否有效
     *
     * @param llmId     LLM ID（格式：model_name@factory）
     * @param modelType 模型类型（可选）
     * @return 验证结果
     */
    @GetMapping("/validate")
    @Operation(summary = "验证LLM ID", description = "验证指定的LLM ID是否有效且已配置")
    public Result<Boolean> validateLLMId(
            @Parameter(description = "LLM ID（格式：model_name@factory）") @RequestParam String llmId,
            @Parameter(description = "模型类型（可选，如：chat, embedding）") @RequestParam(required = false) String modelType) {
        try {
            log.info("收到验证LLM ID请求: llmId={}, modelType={}", llmId, modelType);
            boolean valid = llmService.validateLLMId(llmId, modelType);
            log.info("LLM ID验证结果: llmId={}, valid={}", llmId, valid);
            return Result.success(valid);
        } catch (Exception e) {
            log.error("验证LLM ID失败: llmId={}", llmId, e);
            return Result.error("ERROR", "验证LLM ID失败: " + e.getMessage());
        }
    }

    /**
     * 根据LLM ID查询模型详情
     *
     * @param llmId LLM ID
     * @return 模型详情
     */
    @GetMapping("/detail")
    @Operation(summary = "获取LLM详情", description = "根据LLM ID获取模型详细信息")
    public Result<LLMModelDTO> getLLMDetail(
            @Parameter(description = "LLM ID（格式：model_name@factory）") @RequestParam String llmId) {
        try {
            log.info("收到查询LLM详情请求: llmId={}", llmId);
            RAGFlowLLMClient.LLMModel model = llmService.findModelById(llmId);
            if (model == null) {
                return Result.error("NOT_FOUND", "未找到指定的LLM模型: " + llmId);
            }
            LLMModelDTO dto = convertToDTO(model);
            log.info("成功返回LLM详情: llmId={}", llmId);
            return Result.success(dto);
        } catch (Exception e) {
            log.error("查询LLM详情失败: llmId={}", llmId, e);
            return Result.error("ERROR", "查询LLM详情失败: " + e.getMessage());
        }
    }

    /**
     * 转换为DTO（隐藏API密钥等敏感信息）
     */
    private LLMModelDTO convertToDTO(RAGFlowLLMClient.LLMModel model) {
        LLMModelDTO dto = new LLMModelDTO();
        dto.setLlmName(model.getLlmName());
        dto.setLlmFactory(model.getLlmFactory());
        dto.setModelType(model.getModelType());
        dto.setLlmId(model.getFullLLMId());
        dto.setDisplayName(model.getDisplayName());
        dto.setApiBase(model.getApiBase());
        dto.setCreateTime(model.getCreateTime());
        dto.setUpdateTime(model.getUpdateTime());
        // 不暴露API密钥
        dto.setHasApiKey(model.getApiKey() != null && !model.getApiKey().isEmpty());
        return dto;
    }

    /**
     * LLM模型DTO（数据传输对象，不包含敏感信息）
     */
    @Data
    public static class LLMModelDTO {
        /**
         * 模型名称
         */
        private String llmName;

        /**
         * 工厂名称
         */
        private String llmFactory;

        /**
         * 模型类型（chat, embedding, rerank等）
         */
        private String modelType;

        /**
         * 完整的LLM ID（model_name@factory）
         */
        private String llmId;

        /**
         * 显示名称
         */
        private String displayName;

        /**
         * API基础URL
         */
        private String apiBase;

        /**
         * 是否配置了API密钥（不暴露密钥本身）
         */
        private Boolean hasApiKey;

        /**
         * 创建时间
         */
        private String createTime;

        /**
         * 更新时间
         */
        private String updateTime;
    }
}
